﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using DevExpress.Xpo;
using DevExpress.ExpressApp.Security;
using System.Security.Permissions;
using DevExpress.ExpressApp.Editors;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.Base.Security;
using DevExpress.ExpressApp.Filtering;
using DevExpress.Data.Filtering.Helpers;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Utils;
using System.ComponentModel;

namespace TestPermission.Module
{
    [Custom("Caption", "按钮访问权限")]
    [NonPersistent, DefaultProperty("DisplayName")]
    public class ActionAccessPermission : PermissionBase
    {
        public ActionAccessPermission() { }
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="actionId">按鈕ID</param>
        /// <param name="modifier">權限訪問類型</param>
        public ActionAccessPermission(string actionId, ObjectAccessModifier modifier)
        {
            this.ActionId = actionId;
            this.Modifier = modifier;
        }
        /// <summary>
        /// 顯示名稱
        /// </summary>
        public string DisplayName { get { return this.ToString(); } }
        /// <summary>
        /// 按鈕訪問權限項目List集合
        /// </summary>
        private List<ActionAccessPermissionItem> items = new List<ActionAccessPermissionItem>();

        private ActionAccessPermissionItem GetDesignModeItem()
        {
            if (items.Count > 1)
            {
                throw new InvalidOperationException();
            }
            if (items.Count == 0)
            {
                items.Add(new ActionAccessPermissionItem());
            }
            return items[0];
        }
        /// <summary>
        /// 複製按鈕訪問權限項目
        /// </summary>
        /// <returns></returns>
        private List<ActionAccessPermissionItem> CloneItems()
        {
            List<ActionAccessPermissionItem> clonedItems = new List<ActionAccessPermissionItem>();
            foreach (ActionAccessPermissionItem item in items)
            {
                clonedItems.Add(new ActionAccessPermissionItem(item));
            }
            return clonedItems;
        }
        /// <summary>
        /// 建立目前使用權限和指定之使用權限聯集的使用權限。 
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        public override System.Security.IPermission Union(System.Security.IPermission target)
        {
            ActionAccessPermission result = (ActionAccessPermission)Copy();
            result.items.AddRange(((ActionAccessPermission)target).CloneItems());
            return result;
        }
        /// <summary>
        /// 判斷目前使用權限是否為指定之使用權限的子集。
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        public override bool IsSubsetOf(System.Security.IPermission target)
        {
            if (base.IsSubsetOf(target))
            {
                foreach (ActionAccessPermissionItem targetItem in ((ActionAccessPermission)target).items)
                {
                    if (targetItem.ActionId == ActionId)
                    {
                        return targetItem.Modifier == Modifier;
                    }
                }
                return true;
            }
            return false;
        }
        /// <summary>
        /// 按鈕ID
        /// </summary>
        /// 
        [DataSourceProperty("")]
        public string ActionId
        {
            get { return GetDesignModeItem().ActionId; }
            set { GetDesignModeItem().ActionId = value; }
        }
        /// <summary>
        /// 對象訪問方式
        /// </summary>
        public ObjectAccessModifier Modifier
        {
            get { return GetDesignModeItem().Modifier; }
            set { GetDesignModeItem().Modifier = value; }
        }
        /// <summary>
        /// 使用 XML 編碼方式重建具有指定狀態的安全性物件。
        /// </summary>
        /// <returns></returns>
        public override System.Security.SecurityElement ToXml()
        {
            SecurityElement result = base.ToXml();
            SecurityElement itemElement = new SecurityElement("ActionAccessPermissionItem");

            itemElement.AddAttribute("Modifier", Modifier.ToString());
            itemElement.AddAttribute("ActionId", ActionId);
            result.AddChild(itemElement);
            return result;
        }
        /// <summary>
        /// 建立安全性物件和其目前狀態的 XML 編碼方式。
        /// </summary>
        /// <param name="element"></param>
        public override void FromXml(System.Security.SecurityElement element)
        {
            items.Clear();
            if (element.Children != null)
            {
                if (element.Children.Count != 1)
                {
                    throw new InvalidOperationException();
                }
                SecurityElement childElement = (SecurityElement)element.Children[0];

                Modifier = (ObjectAccessModifier)Enum.Parse(typeof(ObjectAccessModifier), childElement.Attributes["Modifier"].ToString());
                ActionId = childElement.Attributes["ActionId"].ToString();
            }
        }

        public override string ToString()
        {
            return String.Format("{0} - {1}", ActionId, Modifier);
        }
        /// <summary>
        /// 建立並傳回目前使用權限的相同複本
        /// </summary>
        /// <returns></returns>
        public override System.Security.IPermission Copy()
        {
            ActionAccessPermission result = new ActionAccessPermission();
            result.items.AddRange(CloneItems());
            return result;
        }
    }
    public class ActionAccessPermissionItem
    {
        public ActionAccessPermissionItem() { }
        public ActionAccessPermissionItem(ActionAccessPermissionItem source)
        {
            this.ActionId = source.ActionId;
            this.Modifier = source.Modifier;
        }
        public string ActionId { get; set; }
        public ObjectAccessModifier Modifier { get; set; }
    }
}
